package cn.pangza.user.service.impl;

import cn.pangza.common.exception.BusinessException;
import cn.pangza.common.mybatisplus.entity.PageRequest;
import cn.pangza.common.mybatisplus.entity.PageResult;
import cn.pangza.common.redis.service.RedisService;
import cn.pangza.common.utils.MD5Util;
import cn.pangza.common.utils.ResponseData;
import cn.pangza.common.utils.StringUtil;
import cn.pangza.user.constant.UserRedisKeyConstant;
import cn.pangza.user.convert.SystemUserConvert;
import cn.pangza.user.entity.dto.SystemUserDto;
import cn.pangza.user.entity.dto.UserRoleDto;
import cn.pangza.user.entity.po.Employee;
import cn.pangza.user.entity.po.Menu;
import cn.pangza.user.entity.po.Role;
import cn.pangza.user.entity.po.SystemUserPo;
import cn.pangza.user.entity.request.LoginRequest;
import cn.pangza.user.entity.request.SystemUserPageRequest;
import cn.pangza.user.entity.request.UpdateUserRequest;
import cn.pangza.user.entity.vo.GetUserInfoVo;
import cn.pangza.user.entity.vo.SystemUserVo;
import cn.pangza.user.mapper.RoleMapper;
import cn.pangza.user.mapper.SystemUserMapper;
import cn.pangza.user.service.MenuService;
import cn.pangza.user.service.SystemUserService;
import cn.pangza.user.service.TokenService;
import cn.pangza.user.utils.SecurityUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class SystemUserServiceImpl extends ServiceImpl<SystemUserMapper, SystemUserPo> implements SystemUserService {
    private static final String MD5_KEY = "TAOWU-HOUSE";

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    RedisService redisService;

    @Autowired
    MenuService menuService;

    @Autowired
    RoleMapper roleMapper;

    @Autowired
    SystemUserMapper systemUserMapper;

    @Override
    public void createSystemUser(SystemUserDto systemUserDto) {
        SystemUserPo systemUserPo = SystemUserConvert.INSTANCE.systemUserDto2SystemUserPo(systemUserDto);
        systemUserPo.setEnabled(systemUserDto.getEnabled());
        this.save(systemUserPo);
    }

    @Override
    public List<SystemUserVo> getSystemUserList() {
        List<SystemUserPo> list = this.list();
        return list.stream().map(item -> {
            SystemUserVo systemUserVo = SystemUserConvert.INSTANCE.systemUserPo2SystemUserVo(item);
            systemUserVo.setEnabled(item.isEnabled());
            return systemUserVo;
        }).collect(Collectors.toList());
    }

    @Override
    public SystemUserVo login(SystemUserDto systemUserDto) throws BusinessException {
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(systemUserDto.getUsername(), systemUserDto.getPassword());
        Authentication authenticate = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
        SecurityContextHolder.getContext().setAuthentication(authenticate);
        SystemUserPo principal = (SystemUserPo) authenticate.getPrincipal();
        if (ObjectUtils.isEmpty(principal.getEmployeeId())) {
            throw new BusinessException("当前帐号未绑定员工信息，无法登录！");
        }
        Integer employeeId = principal.getEmployeeId();
        Employee employee = systemUserMapper.getEmployeeById(employeeId);
        if(ObjectUtils.isEmpty(employee)) {
            throw new BusinessException("当前帐号未查到员工信息，无法登录！");
        }
        SystemUserVo systemUserVo = SystemUserConvert.INSTANCE.systemUserPo2SystemUserVo(principal);
        List<String> permissionList = principal.getRoleList().stream().map(Role::getName).collect(Collectors.toList());
        List<Menu> menuList = menuService.getMenuListByUserId();
        menuList.forEach(item -> {
            if (StringUtil.isNotEmpty(item.getMeta().getPermission())) {
                permissionList.add(item.getMeta().getPermission());
            }
        });
        systemUserVo.setPermission(permissionList);
        systemUserVo.setRoleZh(principal.getRoleList().stream().map(Role::getNameZh).collect(Collectors.toList()));
        String token = TokenService.generateToken(principal);
        List<Menu> userMenuList = menuService.getUserMenuWithChildren();
        System.err.println(userMenuList);
        systemUserVo.setNickName(employee.getName());
        systemUserVo.setImage(employee.getImage());
        String tokenMd5 = MD5_KEY + principal.getId() + principal.getUsername();
        String tokenResult = MD5Util.encode(tokenMd5);
        systemUserVo.setToken(tokenResult);
        redisService.set(UserRedisKeyConstant.USER_TOKEN + tokenResult, token);
        redisService.set(UserRedisKeyConstant.USER_MENU + principal.getId(), JSONObject.toJSONString(userMenuList));
        redisService.set(UserRedisKeyConstant.USER_INFO + principal.getId(), JSONObject.toJSONString(systemUserVo));
        return systemUserVo;
    }

    @Override
    public PageResult<SystemUserPo> getSystemUserPage(PageRequest<SystemUserPageRequest> pageRequest) {
        Page<SystemUserPo> page = new Page<>(pageRequest.getPageNum(), pageRequest.getPageSize());
        QueryWrapper<SystemUserPo> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("username", "id", "create_time", "enabled");
        if (ObjectUtils.isNotEmpty(pageRequest.getForm())) {
            if (ObjectUtils.isNotEmpty(pageRequest.getForm().getUsername())) {
                queryWrapper.like("username", pageRequest.getForm().getUsername());
            }

            if (ObjectUtils.isNotEmpty(pageRequest.getForm().getPhone())) {
                queryWrapper.like("phone", pageRequest.getForm().getPhone());
            }

            if (ObjectUtils.isNotEmpty(pageRequest.getForm().getEnabled())) {
                queryWrapper.like("enabled", pageRequest.getForm().getEnabled());
            }
        }
        Page<SystemUserPo> resultPage = this.page(page, queryWrapper);
        return PageResult.generatePage(resultPage);
    }

    @Override
    public Boolean createSystemUser(LoginRequest loginRequest) throws BusinessException {
        QueryWrapper<SystemUserPo> selectUserQW = new QueryWrapper<>();
        selectUserQW.eq("username", loginRequest.getUsername());
        selectUserQW.select("id");
        List<SystemUserPo> list = this.list(selectUserQW);
        if(!list.isEmpty()) {
            throw new BusinessException("当前用户名已存在，请勿重复添加！");
        }
        String password = new BCryptPasswordEncoder().encode(loginRequest.getPassword());
        SystemUserPo systemUserPo = new SystemUserPo();
        systemUserPo.setPassword(password);
        systemUserPo.setEnabled(true);
        systemUserPo.setUsername(loginRequest.getUsername());
        return this.save(systemUserPo);
    }

    @Override
    public Boolean updateSystemUser(UpdateUserRequest updateUserRequest) throws BusinessException {
        QueryWrapper<SystemUserPo> selectUserQW =  new QueryWrapper<>();
        selectUserQW.eq("username", updateUserRequest.getUsername());
        selectUserQW.eq("id", updateUserRequest.getId());
        selectUserQW.select("id");
        List<SystemUserPo> list = this.list(selectUserQW);
        if(!list.isEmpty()) {
            throw new BusinessException("当前用户名已存在，请勿重复添加！");
        }
        UpdateWrapper<SystemUserPo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", updateUserRequest.getId());
        updateWrapper.set("username", updateUserRequest.getUsername());
        if(StringUtil.isNotEmpty(updateUserRequest.getPassword())) {
            String password = new BCryptPasswordEncoder().encode(updateUserRequest.getPassword());
            updateWrapper.set("password", password);
        }
        return this.update(updateWrapper);
    }

    @Override
    public Boolean deleteSystemUser(Integer userId) {
        roleMapper.deleteUserRoleByUserId(userId);
        redisService.remove(UserRedisKeyConstant.USER_MENU + userId);
        redisService.remove(UserRedisKeyConstant.USER_INFO + userId);
        roleMapper.deleteUserRoleByUserId(userId);
        return this.removeById(userId);
    }

    @Override
    public GetUserInfoVo getUser(Integer id) {
        SystemUserPo systemUserPo = this.getById(id);
        GetUserInfoVo getUserInfoVo = SystemUserConvert.INSTANCE.systemUserPo2GetUserInfoVo(systemUserPo);
        return getUserInfoVo;
    }

    @Override
    public void updateUserRole(UserRoleDto userRoleDto) {
        roleMapper.removeRoleByUserId(userRoleDto.getUserId());
        if(!userRoleDto.getRoleIds().isEmpty()) {
            roleMapper.updateUserRole(userRoleDto.getUserId(), userRoleDto.getRoleIds());
        }
    }

    @Override
    public List<Integer> getRoleIdsByUserId(Integer id) {
        return roleMapper.getRoleIdsByUserId(id);
    }

}
